package io.kiki.sba.registry.server.data_store.providedata;

import io.kiki.sba.registry.common.model.constants.ValueConstants;
import io.kiki.sba.registry.common.model.metaserver.CompressDatumSwitch;
import io.kiki.sba.registry.common.model.metaserver.CompressPushSwitch;
import io.kiki.sba.registry.common.model.metaserver.ProvideData;
import io.kiki.sba.registry.common.model.store.SubDatum;
import io.kiki.sba.registry.compress.CompressUtils;
import io.kiki.sba.registry.compress.Compressor;
import io.kiki.sba.registry.server.data_store.bootstrap.ServerConfig;
import io.kiki.sba.registry.server.shared.providedata.AbstractFetchSystemPropertyService;
import io.kiki.sba.registry.server.shared.providedata.SystemDataStorage;
import io.kiki.sba.registry.util.JsonUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

public class CompressDatumService extends AbstractFetchSystemPropertyService<CompressDatumService.CompressStorage> {
    private static final Logger logger = LoggerFactory.getLogger(CompressPushSwitch.class);

    @Autowired
    private ServerConfig serverConfig;

    public CompressDatumService() {
        super(ValueConstants.COMPRESS_DATUM_SWITCH_DATA_ID, new CompressStorage(INIT_VERSION, CompressDatumSwitch.defaultSwitch()));
    }

    @Override
    protected int getSystemPropertyIntervalMillis() {
        return serverConfig.getSystemPropertyIntervalMillis();
    }

    @Override
    protected boolean doProcess(CompressStorage expect, ProvideData provideData) {
        final String switchString = ProvideData.toString(provideData);
        if (StringUtils.isBlank(switchString)) {
            logger.info("Fetch compress datum switch content empty");
            return true;
        }
        try {
            CompressDatumSwitch compressDatumSwitch = JsonUtils.read(switchString, CompressDatumSwitch.class);
            CompressStorage update = new CompressStorage(provideData.getVersion(), compressDatumSwitch);
            if (!compareAndSet(expect, update)) {
                return false;
            }
            logger.info("Fetch compress datum switch, prev={}, current={}", expect.compressDatumSwitch, switchString);
            return true;
        } catch (Throwable e) {
            logger.error("Fetch compress datum switch error", e);
        }
        return false;
    }

    protected CompressDatumSwitch getCompressSwitch() {
        return storage.get().compressDatumSwitch;
    }

    public Compressor getCompressor(SubDatum subDatum, String[] encodes) {
        if (subDatum == null) {
            return null;
        }
        CompressDatumSwitch compressDatumSwitch = getCompressSwitch();
        if (!compressDatumSwitch.isEnabled()) {
            return null;
        }
        subDatum.mustUnzipped();
        if (subDatum.getDataBoxSizeCache() < compressDatumSwitch.getCompressMinSize()) {
            return null;
        }
        return CompressUtils.find(encodes);
    }

    protected static class CompressStorage extends SystemDataStorage {
        protected final CompressDatumSwitch compressDatumSwitch;

        public CompressStorage(long version, CompressDatumSwitch compressDatumSwitch) {
            super(version);
            this.compressDatumSwitch = compressDatumSwitch;
        }
    }
}
